//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

//==============================================================
// Created      : Mar-11, 2004
// Author       : juncheng_lau
// Description  : define the interface of the keyboard driver
//==============================================================

#ifndef __ELASTOS_CKBDDIRVER_H__
#define __ELASTOS_CKBDDIRVER_H__

#define KBDBUF              64

typedef struct KBDInfo
{
    uint16_t    uBasePort;
    uint8_t     uIrq;
} KBDInfo;

typedef struct KBDStatus
{
    uint8_t     uScanCode;
    uint8_t     uVirKey;
    uint16_t    uFlags;          //Event type, one of up/down/special
    bool_t      bKeyPress;       // TRUE: Press; FALSE: Release
    uint16_t    uLedStatus;
    uint16_t    uKbdStatus;
    uint8_t     uKeyboardIdentifier;
} KBDStatus;

#define KEYEVENTFLAG_KEYDOWN        0x000
#define KEYEVENTFLAG_KEYUP          0x001
#define KEYEVENTFLAG__SPECIAL_0     0x002
#define KEYEVENTFLAG__SPECIAL_1     0x004
//
//  CKbdDriver
//
class Keyboard : public CDeviceDriver
{
public:
    CARAPI Read(
        /* [in] */ Int64 u64Offset,
        /* [in] */ Int32 bytesToRead,
        /* [out] */ MemoryBuf * pBuffer,
        /* [out] */ IEvent * * ppCompletionEvent);

    CARAPI Write(
        /* [in] */ Int64 u64Offset,
        /* [in] */ const MemoryBuf & buffer,
        /* [out] */ Int32 * pBytesWritten,
        /* [out] */ IEvent * * ppCompletionEvent);

    CARAPI Control(
        /* [in] */ Handle32 nControlCode,
        /* [in] */ const MemoryBuf & inBuffer,
        /* [out] */ MemoryBuf * pOutBuffer,
        /* [out] */ IEvent * * ppCompletionEvent);

    // It's Maybe have no use for the keyboard driver.
    virtual void Dispose() {}

    ECode Initialize(KBDInfo *PortBase);

    // input the scancode, and output at the buffer.
    uint32_t TranslateScancodeToVirtualKeycode(uint8_t c);

    uint32_t SetLedStatus(uint8_t c);

    Keyboard() : m_event()
    {
        m_uPortBase = 0;
        m_uIrq = 0;
        m_uTypematic = 0;
        m_uLedStatus = 0x0002;  // Num Lock Set
        memset(m_virtualKeyCode, 0, sizeof(KBDStatus) * KBDBUF);
        m_uHeader = 0;
        m_uTailer = 0;
        m_uKbdStatus = 0;
    }

private:
    // when the member func Control's first argu equal 0, call this func.
    // Set the keyboard typematic rate.
    // The argument's bound is from 0 to 31.
    ECode SetTypematicRate(
        /* [in] */ uint_t uTypematicRate);

    // when the member func Control's first argu equal 1, call this func
    // Get the keyboard typematic rate.
    ECode GetTypematicRate(
        /* [out] */ uint_t *puTypematicRate);

    // when the member func Control's first argu equal 2, call this func
    // Set the keyboard typematic delay.
    // The argument's bound is from 0 to 3.
    ECode SetTypematicDelay(
        /* [in] */ uint_t uTypematicDelay);

    // when the member func Control's first argu equal 3, call this func
    // Get the keyboard typematic delay.
    ECode GetTypematicDelay(
        /* [out] */ uint_t *puTypematicDelay);

public:
    // keyboard port and irq;
    ioport_t        m_uPortBase;
    uint8_t         m_uIrq;

    // keyboard control
    uint8_t         m_uTypematic;

    // LED status
    uint16_t        m_uLedStatus;

    // CTRL, ALT, SHIFT status;
    uint16_t        m_uKbdStatus;

    // virtual keycode's buffer for application
    KBDStatus       m_virtualKeyCode[KBDBUF];
    uint32_t        m_uHeader;
    uint32_t        m_uTailer;

    // ISR wake up the process that deal with the scancode.
    DzEvent           m_event;
};

extern IDeviceDriver * CDECL CreatePS2Keyboard(uint_t uDeviceNo, void *pvParameter);

#endif  // __ELASTOS_CKBDDIRVER_H__
